package com.jg.visitor.common.utils;

import com.jg.visitor.GlobalConst;
import com.jg.visitor.common.bean.AppConfigs;
import com.jg.visitor.config.autoconfiguration.caffeinecache.service.CacheService;
import com.jg.visitor.config.exception.BaseException;
import com.jg.visitor.controller.dto.UserDTO;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import java.net.URL;



@Slf4j
public class LoginHelper {
    private static final CacheService CACHE_SERVICE = SpringContextHolder.getBean(CacheService.class);
    private static final AppConfigs APP_CONFIGS = SpringContextHolder.getBean(AppConfigs.class);
    private static final Long MILLIS_MINUTE_TEN = 10 * 60 * 1000L;


    //===================================================通用===========================================================
    /**
     * 获取当前请求的域名
     * @return 域名
     */
    public static String getLoginHost(){
        HttpServletRequest request = ContextHolderUtils.getRequest();
        //请求时实际从哪里来的地址
        String referer  = request.getHeader("Referer");

        if(referer == null){
            log.error("getLoginHost error,the referer is null");
            return "";
        }


        try {
            URL url = new URL(referer);
            return url.getHost();
        }catch (Exception e){
            log.error("getLoginHost error,new URL error",e);
        }

        return "";
    }

    /**
     * 获取当前请求的ip
     * @return ip
     */
    public static String getLoginIp(){
        HttpServletRequest request = ContextHolderUtils.getRequest();
        return HttpUtils.getRealIp(request);
    }

    /**
     * 获取当前请求的token
     * @param tokenType token类型 访客或者被访者安全员管理眼 两种
     * @return token
     */
    public static String getRequestToken(String tokenType){
        HttpServletRequest request = ContextHolderUtils.getRequest();
        String token = request.getHeader(tokenType);


        if(StringUtils.isEmpty(token)){
            return null;
        }

        return Base64Utils.decode(token);
    }
    //===================================================通用===========================================================









    //===================================================访客===========================================================
    /***
     * 设置当前登录的访客
     */
    public static void setLoginVisitor(UserDTO user) {
        CACHE_SERVICE.put(GlobalConst.LOGIN_VISITOR,GlobalConst.LOGIN_VISITOR_TOKEN_KEY + user.getToken(),user);
    }

    /***
     * 根据用户类型获取当前登录的访客用户openId
     */
    public static String getLoginVisitorOpenId() {
        try {
            String token = getRequestToken(GlobalConst.VISITOR_TOKEN);

            if(StringUtils.isEmpty(token)){
                log.error("getLoginOpenId error");
                return null;
            }

            return JwtUtils.getOpenIdByJwtTokenAndCheckToken(token);
        } catch (Exception e) {
            log.error("getLoginUser error...",e);
        }
        return null;
    }

    /***
     * 获取当前登录的访客
     */
    public static UserDTO getLoginVisitor() {
        try {
            String requestToken = getRequestToken(GlobalConst.VISITOR_TOKEN);

            if(StringUtils.isEmpty(requestToken)){
                log.error("getLoginOpenId error,token is null");
                return null;
            }

            return CACHE_SERVICE.getCache(GlobalConst.LOGIN_VISITOR,GlobalConst.LOGIN_VISITOR_TOKEN_KEY + requestToken,UserDTO.class);
        } catch (Exception e) {
            log.error("getLoginVisitor error...",e);
        }
        return null;
    }

    /**
     * 建立登录访客token
     */
    public static String createTokenByVisitorOpenId(String visitorOpenId) {
        String jwtToken = JwtUtils.getTokenByOpenId(visitorOpenId);

        return Base64Utils.encode(jwtToken);
    }


    /**
     * 检查访客token有效性 并拿到token中的openId
     * @return 访客openId
     */
    public static String checkVisitorOpenIdSign() {
        String requestToken = getRequestToken(GlobalConst.VISITOR_TOKEN);

        return JwtUtils.getOpenIdByJwtTokenAndCheckToken(requestToken);

    }

    //===================================================访客===========================================================

















    //==================================================后台人员==========================================================
    /***
     * 设置当前登录的管理员被访者安全员
     */
    public static void setLoginUser(UserDTO user) {
        //登录时间
        user.setLoginTime(DateTimeUtil.getTimeNow());
        //登录过期时间
        user.setExpireTime(DateTimeUtil.getTimeStrByLong(System.currentTimeMillis() + APP_CONFIGS.getAdminExpiredTime() * 1000));
        CACHE_SERVICE.put(GlobalConst.LOGIN_ADMIN,GlobalConst.LOGIN_ADMIN_TOKEN_KEY + user.getSnakeToken(),user);
    }

    /**
     * 退出清理退出管理员被访者安全员信息
     */
    public static void loginOutUser() {
        String requestToken = getRequestToken(GlobalConst.ADMIN_TOKEN);

        if(StringUtils.isEmpty(requestToken)){
            throw new BaseException(-1,"token异常无法退出登录！");
        }

        //获取token里面带的snakeToken信息
        String snakeTokenByToken = JwtUtils.getSnakeTokenByToken(requestToken);

        //缓存失效
        CACHE_SERVICE.evict(GlobalConst.LOGIN_ADMIN,GlobalConst.LOGIN_ADMIN_TOKEN_KEY + snakeTokenByToken);
    }

    /***
     * 获取当前登录的管理员被访者安全员
     */
    public static UserDTO getLoginUser() {
        try {
            String requestToken = getRequestToken(GlobalConst.ADMIN_TOKEN);

            if(StringUtils.isEmpty(requestToken)){
                log.error("getLoginOpenId error,token is null");
                return null;
            }

            //获取token里面带的snakeToken信息
            String snakeTokenByToken = JwtUtils.getSnakeTokenByToken(requestToken);

            return CACHE_SERVICE.getCache(GlobalConst.LOGIN_ADMIN,GlobalConst.LOGIN_ADMIN_TOKEN_KEY + snakeTokenByToken,UserDTO.class);
        } catch (Exception e) {
            log.error("getLoginUser error...",e);
        }
        return null;
    }

    /**
     * 建立管理员被访者安全员登录token并且响应请求投带上token
     */
    public static String createTokenBySnakeToken(String snakeToken) {
        String jwtToken = JwtUtils.getTokenBySnakeToken(snakeToken);

        return Base64Utils.encode(jwtToken);
    }

    /**
     * 校验管理员被访者安全员的token是否需要续期
     * @param userDTO 当前登录的管理员被访者安全员
     */
    public static void verifyToken(UserDTO userDTO) {
        long expireTime = DateTimeUtil.getLongByStr(userDTO.getExpireTime());
        long currentTime = System.currentTimeMillis();

        //距离失效时间还剩10分钟以内的请求都需要续期
        if (expireTime - currentTime <= MILLIS_MINUTE_TEN) {
            setLoginUser(userDTO);
        }
    }
    //==================================================后台人员==========================================================
}
